package com.bc004346.travelus;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.bc004346.travelus.dataAccess.SQLHelper;
import com.bc004346.travelus.dataAccess.TravelUsScreenScraper;
import com.bc004346.travelus.dataAccess.asyncTasks.GetProfileTaskFragment;
import com.bc004346.travelus.dataAccess.asyncTasks.LoginTaskFragment;
import com.bc004346.travelus.fragment.FlightListFragment;
import com.bc004346.travelus.model.TravelUsException;
import com.bc004346.travelus.model.TravelUsUnavailableException;
import com.bc004346.travelus.model.abstracts.CustomListActivity;
import com.bc004346.travelus.model.domain.Reservation;
import com.bc004346.travelus.model.interfaces.IGetProfileCallback;
import com.bc004346.travelus.model.interfaces.ILoginCallback;
import com.bc004346.travelus.services.CheckinService;
import com.bc004346.travelus.services.TripMeService;
import com.bc004346.travelus.utility.Utility;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import static com.bc004346.travelus.utility.Utility.HOUR;
import static com.bc004346.travelus.utility.Utility.SHORT_TIME;
import static com.bc004346.travelus.utility.Utility.log;
import static com.bc004346.travelus.utility.Utility.password;
import static com.bc004346.travelus.utility.Utility.seniority;
import static com.bc004346.travelus.utility.Utility.username;

/**
 * Created by Renats on 9/4/2014.
 * The new flight list activity
 */
public class MyFlightListActivity
        extends CustomListActivity
        implements ILoginCallback, IGetProfileCallback {

    public static final String LOGIN_TASK_TAG = "loginTask";
    public static final String PNR_REFRESH_INTENT = "com.bc004346.travelus.pnrRefresh";
    public static final int LOGIN_REQUEST_CODE = 1000;
    protected FlightListFragment mFragment = new FlightListFragment();
    private ProgressBar mHorizontalProgressBar;
    private SQLHelper mSqlHelper;
    private PendingIntent mPendingPnrRefreshIntent;
    private BroadcastReceiver mBroadcastPnrRefreshCheckinReceiver;
    private AlarmManager mAlarmManager;
    private TravelUsScreenScraper mTravelUs;

    //<editor-fold desc="Properties">
    private Context mContext;

    //</editor-fold>

    public SQLHelper getSqlHelper() {
        if (mSqlHelper == null) {
            mSqlHelper = new SQLHelper(getApplicationContext());
        }
        return mSqlHelper;
    }

    @Override
    protected Fragment getFragment() {
        return mFragment;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            mAlarmManager.cancel(mPendingPnrRefreshIntent);

            if (mBroadcastPnrRefreshCheckinReceiver != null)
                unregisterReceiver(mBroadcastPnrRefreshCheckinReceiver);

        } catch (Exception e) {
            Utility.log(e.toString());
            mStatus.setText(e.getMessage());
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        try {
            setTitle("My Flights");
            mSwipeRefresh.setRefreshing(true);
            mTopProgressBar.setVisibility(View.VISIBLE);
            mAlarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);

            mContext = getApplicationContext();
            setupAsyncPnrRefresh();

            mHorizontalProgressBar = (ProgressBar) findViewById(R.id.activity_fragment_progressBarHorizontal);

            if (Utility.username.isEmpty() || Utility.password.isEmpty())
                startLoginActivity();
            else {
                LoginTaskFragment mLoginTaskFragment = (LoginTaskFragment) getFragmentManager().findFragmentByTag(LOGIN_TASK_TAG);

                if (savedInstanceState != null)
                    mFragment.refreshReservations(getSqlHelper().selectReservations());
                else if (mLoginTaskFragment == null) {
                    mStatus.setText(getString(R.string.common_logging_in));
                    mLoginTaskFragment = LoginTaskFragment.newInstance(Utility.username, Utility.password);
                    getFragmentManager().beginTransaction().add(mLoginTaskFragment, LOGIN_TASK_TAG).commit();
                }
            }
            mTravelUs = Utility.getInstance().getTravelUS();

        } catch (Exception e) {
            Utility.log(e.toString());
            if (mStatus != null)
                mStatus.setText(e.getMessage());
            if (mTopProgressBar != null) {
                mTopProgressBar.setVisibility(View.INVISIBLE);
                mSwipeRefresh.setRefreshing(false);
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent resultIntent) {
        try {

            mTopProgressBar.setVisibility(View.INVISIBLE);
            mSwipeRefresh.setRefreshing(false);
            switch (requestCode) {
                case LOGIN_REQUEST_CODE:
                    if (resultCode == RESULT_OK)
                        refresh();
                    else
                        finish();
                    break;
            }
        } catch (Exception e) {
            Utility.log(e.toString());
            mStatus.setText(e.getMessage());
        }
    }

    @Override
    protected void onStop() {
        Utility.onStop(this);
        super.onStop();
    }

    @Override
    public void onLoginPostExecute(Boolean success, Exception e) {
        try {
            mSwipeRefresh.setRefreshing(false);
            mTopProgressBar.setVisibility(View.INVISIBLE);
            if (e != null) {
                if (e.getClass() == TravelUsException.class)
                    mStatus.setText(e.getMessage());
                else if (e.getClass() == TravelUsUnavailableException.class) {
                    log(e);
                    mStatus.setText("Travel US is having problems processing your request. It may be down right now");
                } else {
                    mStatus.setText(String.format(getString(R.string.common_login_has_failed), e.getMessage()));
                    log(e, this);
                }
            } else if (success) {
                mStatus.setText("");
                long target = Utility.pnrRefreshDate.getTime() + Long.valueOf(SettingsActivity.pnrRefreshInterval(this)) * HOUR;
                if (target <= new Date().getTime())
                    refresh();
                else {
                    mFragment.refreshReservations(getSqlHelper().selectReservations());
                    schedulePnrRefresh(new Date(target));

                    //start trip me service for background searches
                    startServices();
                }
            } else {
                mStatus.setText(getString(R.string.dashboardStatus_LoginFailed));
                startLoginActivity();
            }

        } catch (Exception e1) {
            Utility.log(e1.toString());
            mStatus.setText(e1.getMessage());
        }
    }

    @Override
    public void onGetProfilePostExecute(List<Reservation> reservations, Exception e) {

        try {
            mSwipeRefresh.setRefreshing(false);
            mTopProgressBar.setVisibility(View.INVISIBLE);
            mHorizontalProgressBar.setProgress(0);
            removeTaskFragment();

            if (e != null && e.getClass() == TravelUsUnavailableException.class) {
                log(e);
                mStatus.setText("Travel US is having problems processing your request. It may be down right now");
            } else if (e != null) {
                mStatus.setText(e.getMessage());
            } else {
                mStatus.setText("");
                getSqlHelper().MergeReservations(reservations);
                mFragment.refreshReservations(getSqlHelper().selectReservations());

                if (reservations == null || reservations.size() == 0)
                    mStatus.setText(getString(R.string.common_no_flights_found));

                Utility.name = mTravelUs.getName();
                Utility.badge = mTravelUs.getBadge();
                Utility.seniority = mTravelUs.getSeniority();

                schedulePnrRefresh(new Date(new Date().getTime() + Long.valueOf(SettingsActivity.pnrRefreshInterval(this)) * HOUR));
                Utility.pnrRefreshDate = new Date();

                //start trip me service for background searches
                startServices();
            }
        } catch (NumberFormatException e1) {
            Utility.log(e1.toString());
            mStatus.setText(e1.getMessage());
        }
    }

    private void startServices() {
        AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

        Intent checkinIntent = new Intent(this, CheckinService.class);
        PendingIntent checkinPendingIntent = PendingIntent.getService(this, 0, checkinIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, Utility.MINUTE, Utility.HOUR, checkinPendingIntent);

        Intent tripMeIntent = new Intent(this, TripMeService.class);
        tripMeIntent.putExtra(TripMeService.EXTRA_USER, username);
        tripMeIntent.putExtra(TripMeService.EXTRA_PASSWORD, password);
        tripMeIntent.putExtra(TripMeService.EXTRA_SENIORITY, seniority);
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(System.currentTimeMillis());
        cal.set(Calendar.HOUR_OF_DAY, 22);
        cal.set(Calendar.MINUTE, 35);
        PendingIntent tripMePendingIntent = PendingIntent.getService(this, 0, tripMeIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        am.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, tripMePendingIntent);
    }

    @Override
    public void onGetProfileProgressUpdate(String... update) {
        try {
            mHorizontalProgressBar.setProgress(Integer.valueOf(update[0]));
            String s = update[1];
            mStatus.setText(s);
        } catch (NumberFormatException e) {
            Utility.log(e.toString());
            mStatus.setText(e.getMessage());
        }
    }

    private void startLoginActivity() {
        Intent intent = new Intent(this, LoginActivity.class);
        startActivityForResult(intent, LOGIN_REQUEST_CODE);
    }

    public void refresh() {

        try {
            mSwipeRefresh.setRefreshing(true);
            mTopProgressBar.setVisibility(View.VISIBLE);
            GetProfileTaskFragment mGetProfileTaskFragment =
                    (GetProfileTaskFragment) getFragmentManager().findFragmentByTag(getTaskTag());

            toggleMenuState(false);
            // If the Fragment is non-null, then it is currently being
            // retained across a configuration change.
            if (mGetProfileTaskFragment == null) {
                mStatus.setText(getString(R.string.dashboardStatus_RefreshingPNR));
                mGetProfileTaskFragment = GetProfileTaskFragment
                        .newInstance(SettingsActivity.daysToSearch(this));
                getFragmentManager()
                        .beginTransaction()
                        .add(mGetProfileTaskFragment, getTaskTag())
                        .commitAllowingStateLoss();
            }
        } catch (Exception e) {
            Utility.log(e.toString());
            mStatus.setText(e.getMessage());
            mTopProgressBar.setVisibility(View.INVISIBLE);
            mSwipeRefresh.setRefreshing(false);
        }
    }

    private void setupAsyncPnrRefresh() {
        if (mBroadcastPnrRefreshCheckinReceiver == null) {
            mBroadcastPnrRefreshCheckinReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    refresh();
                }
            };
            registerReceiver(mBroadcastPnrRefreshCheckinReceiver, new IntentFilter(PNR_REFRESH_INTENT));
        }
    }

    private void schedulePnrRefresh(Date date) {

        try {

            if (!SettingsActivity.pnrRefreshEnabled(this)) return;

            String message = String.format(getString(R.string.dashboardToast_SchedulingNextPNRRefresh), SHORT_TIME.format(date));

            log(message);

            Intent intent = new Intent("PNR_REFRESH_INTENT");
            try {
                mPendingPnrRefreshIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                        SystemClock.elapsedRealtime() + Integer.valueOf(SettingsActivity.pnrRefreshInterval(this)) * HOUR,
                        mPendingPnrRefreshIntent);
                Utility.pnrRefreshDate = new Date();
                Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
            } catch (Exception e) {
                log(e.toString());
            }
        } catch (Exception e) {
            Utility.log(e.toString());
            mStatus.setText(e.getMessage());
        }
    }

    @Override
    protected String getTaskTag() {
        return "myFlightsListActivityTag";
    }

}
